/**
 * @file:air_conditioning.c
 * @brief:分层状态机
 * @author:liaowx
 * @date:2019.08.02
 */
#include <stdio.h>

#include "air_conditioning.h"

struct air_conditioning const HSM_ROOT =
{
    .parent = ((void *)0),
    .level = 0
};

struct air_conditioning *tran(struct air_conditioning *cur_state,
            struct air_conditioning *next_state)
{
    struct air_conditioning *list_exit[5];
    struct air_conditioning *list_entry[5];
    int cnt_exit = 0;
    int cnt_entry = 0;
    int idx;
    struct air_conditioning *src = cur_state;
    struct air_conditioning *dst = next_state;

    while (src->level != dst->level) {
        if (src->level > dst->level) {
            list_exit[cnt_exit++] = src;
            src = src->parent;
        } else {
            list_entry[cnt_entry++] = dst;
            dst = dst->parent;
        }
    }

    while (src != dst)
    {
        list_exit[cnt_exit++] = src;
        src = src->parent;
        list_entry[cnt_entry++] = dst;
        dst = dst->parent;
    }

    for (idx = 0; idx < cnt_exit; idx++) {
        src = list_exit[idx];
        cur_state = src->handler(cur_state, EXIT);
    }

    for (idx = 0; idx < cnt_entry; idx++) {
        dst = list_entry[cnt_entry - idx - 1];
        cur_state = dst->handler(cur_state, ENTRY);
    }

    cur_state = next_state;
    cur_state = cur_state->handler(cur_state, INIT);

    return cur_state;
}

void state_init(struct air_conditioning *state,
                char *name, int temperature, int wind_speed,
                HSM_FN handler, struct air_conditioning *parent)
{
    if (((void *)0) == parent) {
        parent = (struct air_conditioning *)&HSM_ROOT;
    }

    state->name = name;
    state->temperature = temperature;
    state->wind_speed = wind_speed;
    state->handler = handler;
    state->parent = parent;
    state->level = parent->level + 1;
}

struct air_conditioning *state_run(struct air_conditioning *cur_state, enum EVENT event)
{
    cur_state = cur_state->handler(cur_state, event);

    return cur_state;
}

struct air_conditioning *state_creat(struct air_conditioning *cur_state,
                                    struct air_conditioning *init_state)
{
    cur_state->name = init_state->name;
    cur_state->temperature = init_state->temperature;
    cur_state->wind_speed = init_state->wind_speed;
    cur_state->handler = init_state->handler;
    cur_state->parent = init_state->parent;
    cur_state->level = init_state->level;

    return cur_state;
}